/***********************************************************************************************//**
*\n  @file       usb_udp.c
*\n  @brief      usb��̫��ģ�鴫������
*\n  @details
*\n -----------------------------------------------------------------------------------
*\n  �ļ�˵����
*\n       1. ��udp/ip����ͼ��PCʵʱ��ʾ��
*\n       2. ����ͼ��Ϊ: (1).640*360�ĻҶ�ͼ��
*\n                      (2).����640*360 YUV420��ͼ
*\n                      (3).����1280*720 jpeg��ͼ
*\n       3. ���ݲ����֡��ÿ�δ���2������(��Լ= 2*640Bytes + 4Bytesͷ��Ϣ  )
*\n       4. ����upd server�˿ڣ��ֱ����ڴ���ͼ��,���ò�����
*\n       
*\n -----------------------------------------------------------------------------------
*\n  �汾:		�޸��ˣ�		�޸�����:       ����:
*\n  V0.1		������	  		2018.11.12	����
*\n 
***************************************************************************************************/

/**************************************************************************************************
* ͷ�ļ�
***************************************************************************************************/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include<netinet/in.h>
#include<netinet/tcp.h>
#include <sys/time.h>
#include <termios.h>
#include <errno.h>
#include <errno.h>
#include <pthread.h>

#include "util.h"
#include "printf.h"
#include "vdma.h"

#include "usb_udp.h"

//#include "jpeglib.h"
#include "turbojpeg.h"



#if UDP_ENABLE
/**************************************************************************************************
* �궨�塢�ṹ����
***************************************************************************************************/
//#define CAM_HSIZE  				(1280)
//#define CAM_VSIZE  				(720)
//#define SERAIAL_WIDTH			(1280/2)
//#define SERAIAL_HEIGHT			(720/2)
#define SERAIAL_WIDTH			(1920/2)
#define SERAIAL_HEIGHT			(1080/2)

#define SERVER_PORT				(60000)			///< UDP sever�˿ں�(ͼ������)
#define SERVER_PORT1			(60001)			///< UDP sever�˿ں�(���ò���)

#define FRAME_DATA_SIZE   		(2*640)  		///< ����ͼ��֡�����ݳ���
//#define FRAME_DATA_SIZE   		(2*960)  		///< ����ͼ��֡�����ݳ���

//#define RECV_BUFF_LEN 			(2048)
//#define SEND_BUFF_LEN 			(2048)
#define RECV_BUFF_LEN 			(4096)
#define SEND_BUFF_LEN 			(4096)


/// ͼ����֡��ʽ
typedef struct UpdSendFrame
{
	uint8_t  	u8Type;		///< 0x0f=640x360 GRAY, 0x10=640x360 I420
	uint8_t  	u8Flags;	///< 1��ʼ���ģ�2�м䱨�ģ�3����ģ�4����֡(��ʼ+��������)
	uint16_t 	u16Index;	///< ֡���(0,1,2....)
	uint8_t  	u8Date[];	///< ����buf(2������640*2 bytes)
}	TUpdSendFrame;

/// UDP����Handler
typedef struct UdpHandler
{
	int8_t		s8Name[40];
	int32_t		s32Flags;
	pthread_t 	tidTask;
	int32_t		s32ServerFd;
	int32_t		s32ServerPort;				///< �����˿�
	socklen_t 	tLength;
	struct sockaddr_in 	sClientAddress; 	///< client��ַ
	struct sockaddr_in 	sServerAddress; 	///< server��ַ

	int32_t 	s32Enable;            		///< send����
	int8_t		s8SendBuf[SEND_BUFF_LEN];	///< ����buf
	int32_t  	s32SendSize;				///< ����size
	int8_t 		s8RecvBuf[RECV_BUFF_LEN];	///< ����buf
	int32_t		s32RecvSize;				///< ����size
}	TUdpHandler;


/**************************************************************************************************
* ȫ�ֱ�������������
***************************************************************************************************/


/**************************************************************************************************
* ˽�б�������������
***************************************************************************************************/
// USB server(ͼ��˿�)
static TUdpHandler tUdpHandler =
{
	.s8Name			= "tUdpHandler",
	.s32Flags 		= 0,
	.s32ServerFd  	= -1,
	.s32ServerPort	= SERVER_PORT,  ///< �����˿�
	.tidTask 		= -1,
	.sClientAddress = {0},
	.sServerAddress = {0},
	.tLength 		=  sizeof(struct sockaddr_in),

	.s32Enable 		= 0,
	.s8RecvBuf 		= {0},
	.s32RecvSize 	= -1
};

// USB server(�����˿�)
static TUdpHandler tUdpHandler1 =
{
	.s8Name			= "tUdpHandler1",
	.s32Flags 		= 0,
	.s32ServerFd  	= -1,
	.s32ServerPort	= SERVER_PORT1,	///< �����˿�
	.tidTask 		= -1,
	.sClientAddress = {0},
	.sServerAddress	= {0},
	.tLength 		=  sizeof(struct sockaddr_in),

	.s32Enable 		= 0,
	.s8RecvBuf 		= {0},
	.s32RecvSize 	= -1
};


/**************************************************************************************************
* ��������������
***************************************************************************************************/

/// ���Ϳ��أ� 0=�أ�1=��
static void EnableUdpSend(TUdpHandler *this, int32_t enable)
{
	this->s32Enable = (enable == 0) ? 0 : 1;
}

/// udp server�߳�
static void* UdpTask(void* arg)
{
	int iRet;
	TUdpHandler *this = arg;
	

    this->s32ServerFd = socket(AF_INET, SOCK_DGRAM, 0);
    if(this->s32ServerFd < 0)
    {
        printf("create socket fail!\n");
        return NULL;
    }

    memset(&this->sServerAddress, 0, sizeof(this->sServerAddress));
    this->sServerAddress.sin_family      = AF_INET;
    this->sServerAddress.sin_addr.s_addr = htonl(INADDR_ANY);
    this->sServerAddress.sin_port        = htons(this->s32ServerPort);

    iRet = bind(this->s32ServerFd, (void*)&this->sServerAddress, sizeof(this->sServerAddress));
    if(iRet < 0)
    {
        printf("socket bind fail!\n");
        // return -1;
        goto exit1;
    }

	memset(this->s8RecvBuf, 0, sizeof(this->s8RecvBuf));
    while(1)
    {
        int iCnts = recvfrom(this->s32ServerFd, this->s8RecvBuf, sizeof(this->s8RecvBuf), 
							 0, (void*)&this->sClientAddress, &this->tLength); 
        if(iCnts < 0)
        {
            continue;
        }
		this->s8RecvBuf[iCnts] = '\0';
        dbg_debug("s8RecvBuf[%d]:%s\n", iCnts, this->s8RecvBuf);  

		if (0 ==strncmp((void*)this->s8RecvBuf, "start\r", 5))   // �������start��
		{
			EnableUdpSend(this, 1);
			this->s32RecvSize = -1;
		}
		else if (0 ==strncmp((void*)this->s8RecvBuf, "stop\r", 4))  // �������stop��
		{
			EnableUdpSend(this, 0);
			this->s32RecvSize = -1;
		}
		else
		{
			this->s32RecvSize = iCnts;  // �û����ݳ���
			// dbg_debug("this->s32RecvSize == %d\n", count);
		}
    }

exit1:
    close(this->s32ServerFd);
    return NULL;
}


/*************************************************************************************//**
*\n �������ƣ� InitUpdTask()
*\n ����������
*\n            ��ʼ��udp������udp server�߳�
*\n ���������
*\n            void  
*\n �������: 
*\n            
*\n �� �� ֵ: 
*\n           =0: �ɹ�           
*\n           <0: ʧ��(������)
*\n
*\n -----------------------------------------------------------------------------------
*\n  �汾:    �޸���:       �޸�����:         ����:
*\n  V0.1   ������        2018.11.13    ����
*****************************************************************************************/
static int InitUpdTask(TUdpHandler *this)
{
	int iRet;
	
	iRet = pthread_create(&this->tidTask, NULL,  UdpTask, this);
	if(iRet < 0)
	{
		dbg_error("pthread_create(UdpTask) failed : %s\n", strerror(iRet));
		return -1;
	}

	dbg_debug("InitUpdTask(%s) done \n", this->s8Name);
	return 0;
}


/*************************************************************************************//**
*\n �������ƣ� SendToUdp()
*\n ����������
*\n            ����udp����
*\n            ���ݲ����֡�����ͷ��Ϣ��ÿ�η���2������(2*640Bytes)
*\n ���������
*\n            void *buf  : ��������
*\n            int size   : ����
*\n            int type   : ���� 0x0f=640x360 GRAY, 0x10=640x360 YUV420
*\n �������: 
*\n            
*\n �� �� ֵ: 
*\n            >0: ���ͳ���
*\n            <0: ʧ��(������)
*\n         
*\n -----------------------------------------------------------------------------------
*\n  �汾:    �޸���:       �޸�����:         ����:
*\n  V0.1   ������        2018.11.14    ����
*****************************************************************************************/
static ssize_t SendToUdp(TUdpHandler *this, char *buf, int size, uint8_t type)          
{
	if ((this->s32ServerFd < 0) || (this->s32Enable == 0))
	{
		return -1;
	}

	int iRet = -1;
	int iDiff = 0;
	int iNo = 0;
	int iTotalCnts = 0;  // ���������ܳ���
	int iErrorCnts = 0;
	TUpdSendFrame  *pFrame = (void*)this->s8SendBuf;

	// ÿ�η���4bytesͷ��Ϣ+2������
	iNo = 0;
	while(size > iNo)
	{
	loop1:
		iDiff = size - iNo;
		if (iDiff > FRAME_DATA_SIZE)
		{
			// ���ݷְ�����֡������
			// ͷ��Ϣ����
			pFrame->u8Type = type;
			if (iNo == 0)
			{
				pFrame->u8Flags = 1;  // ��1֡
			}
			else
			{
				pFrame->u8Flags = 2;  // �м�֡
			}
			pFrame->u16Index = iNo / (FRAME_DATA_SIZE);
			
			// ���ݴ���
			memcpy(pFrame->u8Date, buf+iNo,  FRAME_DATA_SIZE);
			iRet = sendto(this->s32ServerFd, (void*)pFrame, FRAME_DATA_SIZE+4,
						 0, (void*)&this->sClientAddress, sizeof(this->sClientAddress)); 
			iNo += FRAME_DATA_SIZE;
			if (iRet < 0) 
			{
				if (iErrorCnts++ > 20) 
				{
					// ����������ʾ��̫��Ӳ�����ϣ�ֹͣ����
					EnableUdpSend(this, 0);
					return -1;
				}
				dbg_error("sendto(),index=%d \n", (int)pFrame->u16Index);
				goto loop1;  //continue;
			}
			iTotalCnts += FRAME_DATA_SIZE;
			iErrorCnts = 0;
		}
		else
		{
			// �������֡
			pFrame->u8Type = type;
			if (iNo == 0)
			{
				pFrame->u8Flags = 4;  // ����֡(��ʼ+��������)
			}
			else
			{
				pFrame->u8Flags = 3;  // ���֡
			}
			pFrame->u16Index = iNo / (FRAME_DATA_SIZE);
			
			memcpy(pFrame->u8Date, buf+iNo,  iDiff);
			iRet = sendto(this->s32ServerFd, (void*)pFrame, iDiff+4, 
						 0, (void*)&this->sClientAddress, sizeof(this->sClientAddress)); 
			iNo += iDiff;
			if (iRet < 0) 
			{
				if (iErrorCnts++ > 20) 
				{
					// ����������ʾ��̫��Ӳ�����ϣ�ֹͣ����
					EnableUdpSend(this, 0);
					return -1;
				}
				dbg_error("sendto() error: index=%d \n", (int)pFrame->u16Index);
				goto loop1; //continue;
			}
			iTotalCnts += iDiff;
			iErrorCnts = 0;
		}
	}
		
	return iTotalCnts;
}

/// ����ԭʼ����
static ssize_t SendToUdp1(TUdpHandler *this, char *buf, int size, uint8_t type)          
{
	if (this->s32ServerFd < 0)
		return -1;
	
	ssize_t ret = sendto(this->s32ServerFd, (void*)buf, size, 
				 		 0, (void*)&this->sClientAddress, sizeof(this->sClientAddress)); 
		
	return ret;
}

/*************************************************************************************//**
*\n �������ƣ� ReadFromUdp()
*\n ����������
*\n            ��ȡ���յ�����
*\n ���������
*\n            TUdpHandler *this   : ���
*\n            uint8_t             ������buf
*\n            int32_t length      ��buf����
*\n �������: 
*\n            unsigned char *buf  ����ȡ������
*\n            
*\n �� �� ֵ: 
*\n           >0: ���ݳ���
*\n           <0: ʧ��(������)
*\n
*\n -----------------------------------------------------------------------------------
*\n  �汾:    �޸���:       �޸�����:         ����:
*\n  V0.1   ������        2018.11.16    ����
*****************************************************************************************/
static ssize_t ReadFromUdp(TUdpHandler *this, uint8_t *buf, int32_t s32Size)
{
	if (this->s32RecvSize <= 0)
		return -1;

	int32_t iSize = this->s32RecvSize < s32Size ? this->s32RecvSize : s32Size;
	memcpy(buf, this->s8RecvBuf, iSize);
	
	this->s32RecvSize = -1;
	
	return iSize;
}

///  ����������д���ļ�
static size_t Write2File(char *filename, uint8_t *buf, int size)
{
	size_t ret;
	
	FILE *fJpg = fopen(filename, "wb");
    if(fJpg == NULL){
        printf("Cannot open file %s, %s\n", filename, strerror(errno));
        return -1;
    }
	ret = fwrite(buf, 1, size, fJpg);
	fclose(fJpg);

	return ret;
}


#if 0
/*************************************************************************************//**
*\n �������ƣ� tyuv2jpeg()
*\n ����������
*\n            YUV420Pתjpeg��ʽ (����ʱ��Ϊ99mS)
*\n ���������
*\n            JSAMPLE *pYUVBuffer   : yuv����
*\n            int width             : �� x ��
*\n            int height            
*\n            size_t *dest_size     : jpeg�����С
*\n �������: 
*\n            uint8_t *jpeg_buffer  : jpegͼ��
*\n            size_t *dest_size     : jpeg��С
*\n            
*\n �� �� ֵ: 
*\n           =0: �ɹ�           
*\n           <0: ʧ��(������)
*\n
*\n -----------------------------------------------------------------------------------
*\n  �汾:	 �޸���:       �޸�����:       	 ����:
*\n  V0.1    ������        2018.12.12        ����
*****************************************************************************************/
static int tyuv2jpeg1(/*OUT*/uint8_t *jpeg_buffer,  /*INOUT*/ size_t *dest_size,
							JSAMPLE *pYUVBuffer, int width, int height)
{
    JSAMPROW row_pointer[1];
    int row_stride;
    int i = 0, j = 0;
    unsigned char yuvbuf[width * 3];
    unsigned char *pY, *pU, *pV;
    int ulen;

    if(pYUVBuffer == NULL){
        printf("pBGRBuffer is NULL!\n");
        return -1;
    }

	struct jpeg_error_mgr jerr;
	struct jpeg_compress_struct cinfo;
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);
	jpeg_mem_dest(&cinfo, &jpeg_buffer, (unsigned long*)dest_size);

    cinfo.image_width = width;
    cinfo.image_height = height;
    cinfo.input_components = 3;
    cinfo.in_color_space = JCS_YCbCr;
    cinfo.dct_method = JDCT_ISLOW;
    jpeg_set_defaults(&cinfo);

    jpeg_set_quality(&cinfo, 80, TRUE);
    jpeg_start_compress(&cinfo, TRUE);
    row_stride = cinfo.image_width * 3; 
    
	ulen = width * height / 4;
    pY = pYUVBuffer;
    pU = pYUVBuffer + width*height;
    pV = pYUVBuffer + width*height + ulen;
    j = 1;
    while (cinfo.next_scanline < cinfo.image_height) {
        if(j % 2 == 1 && j > 1){
            pU = pYUVBuffer + width*height + width / 2 * (j / 2);
            pV = pYUVBuffer + width*height * 5 / 4 + width / 2 *(j / 2);
        }
        for(i = 0; i < width; i += 2){
            yuvbuf[i*3] = *pY++;
            yuvbuf[i*3 + 1] = *pU;
            yuvbuf[i*3 + 2] = *pV;

            yuvbuf[i*3 + 3] = *pY++;
            yuvbuf[i*3 + 4] = *pU++;
            yuvbuf[i*3 + 5] = *pV++;
        }

        row_pointer[0] = yuvbuf;
        (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
        j++;
    }
    jpeg_finish_compress(&cinfo);
    jpeg_destroy_compress(&cinfo);
    return 0;
}
							
size_t serial_send_data(void *yuv_buf, int len,  EUsbFrameType type)
{
	static int flags = 0;

	size_t	size = 1280 * 720;
	int sendLen = 0;

	if ((type == E_USB_FRAME_GRAY) || (type == E_USB_FRAME_YUV420P) || (type == E_USB_FRAME_JPEG))
	{

		/*******  ���Դ���, jpeg����ͼ��д���ļ�   *****************/
		static uint8_t	__attribute__((aligned (2))) jpeg_buf[SERAIAL_WIDTH * SERAIAL_HEIGHT*3/2];
		size_t size = 0;
		if (flags++ == 50)
		{
			int last_time = get_timer_now();
			tyuv2jpeg(jpeg_buf, &size,	yuv_buf, 1280, 720);
			int curr_time = get_timer_now();
			Write2File("/cam.jpg", jpeg_buf, size);
			dbg_error("write /cam.jpg, time=%d \n", (curr_time-last_time));
		}
	}
	return 0;
}
#endif

/*************************************************************************************//**
*\n �������ƣ� tyuv2jpeg1()
*\n ����������
*\n            YUV420Pתjpeg��ʽ (����ʱ��Ϊ40mS)
*\n ���������
*\n            unsigned char* yuv_buffer    : yuv����
*\n            int width                    : ��*��
*\n            int height                   
*\n            int subsample                : TJSAMP_420, TJSAMP_422,TJSAMP_GRAY, etc
*\n �������: 
*\n            unsigned char** jpeg_buffer  : �����ڲ�malloc���ɻ��壬�ⲿ��Ҫfree()
*\n            unsigned long* jpeg_size     : jpeg��С
*\n            
*\n �� �� ֵ: 
*\n           =0: �ɹ�   
*\n           <0: ʧ��(������)      
*\n           
*\n -----------------------------------------------------------------------------------
*\n  �汾:   �޸���:       �޸�����:        ����:
*\n  V0.1  ������        2018.12.17   ����
*****************************************************************************************/
static int tyuv2jpeg(unsigned char* yuv_buffer,  int width, int height, int subsample, 
					 unsigned char** jpeg_buffer, unsigned long* jpeg_size)
{
    tjhandle handle = NULL;
    int flags = 0;
    int padding = 1; // 1��4���ɣ���������0
    int need_size = 0;
    int ret = 0;

	int yuv_size = width * height * 3/2;
    handle = tjInitCompress();
    need_size = tjBufSizeYUV2(width, padding, height, subsample);
    if (need_size != yuv_size)
    {
		tjDestroy(handle);
        printf("we detect yuv size: %d, but you give: %d, check again.\n", need_size, yuv_size);
        return -1;
    }
 
	int quality = 80; // ѹ����(1 ~ 100)
	flags |= 0;
    ret = tjCompressFromYUV(handle, yuv_buffer, width, padding, height, 
    						subsample, jpeg_buffer, jpeg_size, quality, flags);
    if (ret < 0)
    {
        printf("compress to jpeg failed: %s\n", tjGetErrorStr());
    }
    tjDestroy(handle);
    return ret;
}



/*��ȡ��ǰms��*/
static int get_timer_now ()
{
    struct timeval now;
    gettimeofday(&now, NULL);
    return(now.tv_sec * 1000 + now.tv_usec / 1000);
}




/**************************************************************************************************
* ȫ�ֺ�������������
***************************************************************************************************/

#if 1
/*************************************************************************************//**
*\n �������ƣ� udp_send_data()
*\n ����������
*\n            ͼ��ת����������ͼ�����ݵ�PC�ͻ���
*\n            1. ��ԭͼ(1280x720)��С��(640x360)����
*\n            2. ���Է��ͻҶ�ͼ������yuv420�Ĳ�ͼ
*\n ���������
*\n            void *src   : ԭͼ����(1280x720��yuv420pͼ��)
*\n            int len     : ԭͼ����
*\n            int type    : usb����ͼ������
*\n             			 0x0e :ת��Ϊ1280x720   jpeg��ͼ
*\n             			 0x0f :ת��Ϊ640x360�Ҷ�ͼ
*\n            				 0x10 :ת��Ϊ640x360��yuv420p��ͼ��
*\n �������: 
*\n            
*\n �� �� ֵ: 
*\n           >0: ���ͳ���          
*\n           <0: ʧ��(������)
*\n
*\n -----------------------------------------------------------------------------------
*\n  �汾:    �޸���:       �޸�����:         ����:
*\n  V0.1   ������        2018.11.15    ����
*****************************************************************************************/
ssize_t udp_send_data(void *src, int len, int type)
{
	static uint8_t  __attribute__((aligned (2))) dest[SERAIAL_WIDTH * SERAIAL_HEIGHT*3/2];
	size_t size = 0;
	int ret;
	
	TUdpHandler *this = &tUdpHandler;
	if (this->s32Flags != 0x55)
	{
		//��ʼ����̫��
		InitUpdTask(this);
		usleep(10000);
		this->s32Flags = 0x55;
	}

	// �����ж�
	if (this->s32Enable == 0) 
	{
		//dbg_error("udp Enable == 0\n");
		return -1;
	}
	

	//	ͼ������һ��
	//	void image_scale_2x2_to_1x1(BYTE *src_data, BYTE *dst_data, int src_w, int src_h);
	int sendLen = -1;
	uint8_t *pSrc = src;
	if (type == E_USB_FRAME_YUV420P)
	{
		image_scale_2x2_to_1x1(pSrc,			  dest, 								 CAM_HSIZE,   CAM_VSIZE);	  // y
		image_scale_2x2_to_1x1(pSrc+CAM_HSIZE*CAM_VSIZE,     dest+SERAIAL_WIDTH*SERAIAL_HEIGHT,     CAM_HSIZE/2, CAM_VSIZE/2);  // u
		image_scale_2x2_to_1x1(pSrc+CAM_HSIZE*CAM_VSIZE*5/4, dest+SERAIAL_WIDTH*SERAIAL_HEIGHT*5/4, CAM_HSIZE/2, CAM_VSIZE/2);  // v
		sendLen = SendToUdp(this, (void*)dest, SERAIAL_WIDTH*SERAIAL_HEIGHT*3/2, type); 	 
	}
	else if (type == E_USB_FRAME_JPEG)
	{
		// jpegͼ��
		unsigned char *jpeg_buf = NULL;
		unsigned long jpeg_size = 0;
		int last_time = get_timer_now();
		ret = tyuv2jpeg(src, CAM_HSIZE, CAM_VSIZE, TJSAMP_420,  &jpeg_buf, &jpeg_size);
		int curr_time = get_timer_now();
		if (ret < 0) 
		{
			dbg_error("tyuv2jpeg() error");
			if (jpeg_buf != NULL) 
				free(jpeg_buf);
			return -1;
		}

		#if 0
			/*******  ���Դ���, jpegд���ļ�   *****************/
			static int flags = 0;
			if (flags++ == 200)
			{
				Write2File("/cam.jpg", jpeg_buf, jpeg_size);
				dbg_error("write /cam.jpg, time = %d mS\n", (curr_time-last_time));
			}
		#endif

		sendLen = SendToUdp(this, (void*)jpeg_buf, jpeg_size, type); 
		free(jpeg_buf);  // �ͷ��ڴ�
	}

	return sendLen;
}


/*************************************************************************************//**
*\n �������ƣ� udp_send_data1()
*\n ����������
*\n            �������ö˿ڷ������ò���
*\n ���������
*\n            void *src           
*\n            int len             
*\n            int type  
*\n �������: 
*\n            
*\n �� �� ֵ: 
*\n           =0: �ɹ�           
*\n           <0: ʧ��(������)
*\n
*\n -----------------------------------------------------------------------------------
*\n  �汾:    �޸���:       �޸�����:         ����:
*\n  V0.1   ������        2018.11.16    ����
*****************************************************************************************/
ssize_t udp_send_data1(void *src, int len, int type)
{

	TUdpHandler *this = &tUdpHandler1;
	if (this->s32Flags != 0x55)
	{
		//��ʼ����̫��
		InitUpdTask(this);
		usleep(10000);
		this->s32Flags = 0x55;
	}

	int size = SendToUdp1(this, (void*)src, len, type);      
	return size;
}



/// 
//  ����ֵ��  <0=ʧ��;
/*************************************************************************************//**
*\n �������ƣ� udp_receive_data()
*\n ����������
*\n            ��ȡͼ��˿ڵĽ��յ�����
*\n ���������
*\n            void *buf     ������buf
*\n            int len       ��buf����
*\n �������: 
*\n            int *rcv_len  ���������ݳ���
*\n            
\n            
*\n �� �� ֵ: 
*\n           >0: �������ݳ���
*\n           <0: ʧ��(������)      
*\n -----------------------------------------------------------------------------------
*\n  �汾:   �޸���:       �޸�����:        ����:
*\n  V0.1  ������        2018.12.14   ����
*****************************************************************************************/
int udp_receive_data(void *buf, int len, int *rcv_len)
{
	TUdpHandler *this = &tUdpHandler;
	if (this->s32Flags != 0x55)
	{
		//��ʼ����̫��
		InitUpdTask(this);
		usleep(10000);
		this->s32Flags = 0x55;
	}

    int size = ReadFromUdp(this, buf, len);
	if (rcv_len != NULL	)
		*rcv_len = size;
	
    return size;
}


/*************************************************************************************//**
*\n �������ƣ� udp_receive_data()
*\n ����������
*\n            ��udp����buf��ȡ����(������)
*\n            1. ��ȡ�������ö˿ڽ��յ�����(SERVER_PORT1)
*\n ���������
*\n            void *buf     ������buf
*\n            int len       ��buf����
*\n �������: 
*\n            int *rcv_len  ���������ݳ���
*\n            
*\n �� �� ֵ: 
*\n           >0: type��־ 
*\n           <0: ʧ��(������)
*\n
*\n -----------------------------------------------------------------------------------
*\n  �汾:    �޸���:       �޸�����:         ����:
*\n  V0.1   ������        2018.11.16    ����
*****************************************************************************************/
int udp_receive_data1(void *buf, int len, int *rcv_len)
{
	TUdpHandler *this = &tUdpHandler1;
	if (this->s32Flags != 0x55)
	{
		//��ʼ����̫��
		InitUpdTask(this);
		usleep(10000);
		this->s32Flags = 0x55;
	}

    int size = ReadFromUdp(this, buf, len);
    if (size <= 8) 
	{
        return -1;
    }
	dbg_info("usb recv data[%d]\n", size);

    unsigned char *p_buf = buf;
    if (p_buf[0] != 'J' || p_buf[1] != 'M' || p_buf[2] != 0) 
	{
        return -1;
    }
    int type = p_buf[3];
    int checkLen = *(unsigned int *)(p_buf + 4);
    if (checkLen > len) 
	{
        fprintf(stderr, "Receive size is too large %d\n", checkLen);
        return -1;
    }
	if (rcv_len != NULL	)
    	*rcv_len = checkLen;
	
    if (checkLen != size) 
	{
        fprintf(stderr, "Receive file size error %d / %d\n", size, checkLen);
        return -1;
    }
    return type;
}
#endif


#if 1
/*************************************************************************************//**
*\n �������ƣ� serial_send_data()
*\n ����������
*\n            ����ͼ�����ݵ�PC
*\n ���������
*\n            void *yuv_buf       : YUV420P 1280*720ԭͼ����(�������ò���)
*\n            int len             ������
*\n            EUsbFrameType type  : �������ͣ���������ͣ�
*\n �������: 
*\n            
*\n �� �� ֵ: 
*\n           =0: �ɹ�   
*\n           <0: ʧ��(������)      
*\n           
*\n -----------------------------------------------------------------------------------
*\n  �汾:   �޸���:       �޸�����:        ����:
*\n  V0.1  ������        2018.12.18   ����
*****************************************************************************************/
size_t serial_send_data(void *yuv_buf, int len,  int type)
{
	static int flags = 0;

	size_t	size = 1280 * 720;
	int sendLen = 0;


	if ((type == E_USB_FRAME_YUV420P) || (type == E_USB_FRAME_JPEG))
	{
		int sendLen = 0;
		sendLen = udp_send_data(yuv_buf, len, type);
		if (sendLen <= 0)
		{
			// �رմ���
			dbg_error("send err, %d \r\n", sendLen);
		}
	}
	else
	{
		// �������ò���
		sendLen = udp_send_data1(yuv_buf, len, type);
		dbg_debug("usb send %dB ok.", sendLen);

	}
	return sendLen;
}

int serial_receive_data(void *data, int len, int *rcv_len)
{
	int type = udp_receive_data1(data, len, rcv_len);
	
	return type;
}
int serial_send_probe(int is_force)
{
	return 0;
}

#endif


#endif  // #if UDP_ENABLE





/**************************************************************************************************
* ���Դ���
***************************************************************************************************/
#if UDP_ENABLE

static uint8_t yuv422[CAM_HSIZE * CAM_VSIZE * 4] = {	0,};
static uint8_t yuv420[CAM_HSIZE * CAM_VSIZE * 4] = {	0,};

/***************************************************************************/ /**
*\n �������ƣ� yuv422_to_yuv420()
*\n ����������
*\n            yuv422תyuv420
*\n ���������
*\n            uint8_t *pyuv422  : ��camera�����ͼ��(1280*720)
*\n �������: 
*\n            uint8_t *pyuv420  : ���yuv420ͼ��(1280*720)
*\n            
*\n �� �� ֵ:
*\n            ������ݳ���
*\n
*\n -------------------------------------------------------------------------
*\n  �汾:    �޸���:       �޸�����:         ����:
*\n   V0.1 	������ 		2018.8.6    	����
*******************************************************************************/
int yuv422_to_yuv420(/*out*/ uint8_t *pyuv420, uint8_t *pyuv422)
{
	
	typedef struct _TYuv422UYVY_
	{ // yuyv �ܿ������������Ǽ���ģ�ͼ����
		uint8_t u;
		uint8_t y0;
		uint8_t v;
		uint8_t y1;
	} TYuv422UYVY;
	
	typedef struct _TRGB565_
	{
		uint16_t v0;
		uint16_t v1;
	} TRGB565;


	int w = CAM_HSIZE;
	int h = CAM_VSIZE;

	//uint8_t *pyuv422 = pyuv420;

	int half_w = w >> 1;

	TYuv422UYVY *psrc = (TYuv422UYVY *)pyuv422;
	TYuv422UYVY *psrc1 = &psrc[half_w];

	int uv_step = w >> 1;
	uint8_t *py0 = pyuv420;
	uint8_t *py1 = py0 + w;
	uint8_t *pu = py0 + w * h;
	uint8_t *pv = pu + ((w * h) >> 2);
	for (int y = 0; y < h; y += 2)
	{
		for (int x = 0; x < (half_w); x++)
		{
			*py0++ = psrc->y0;
			*py0++ = psrc->y1;

			*py1++ = psrc1->y0;
			*py1++ = psrc1->y1;

			*pu++ = (psrc->u + psrc1->u) >> 1;
			*pv++ = (psrc->v + psrc1->v) >> 1;

			psrc++;
			psrc1++;
		}
		psrc += half_w;
		psrc1 += half_w;

		py0 += w;
		py1 += w;
	}

	return w * h * 3 / 2;
}

/***************************************************************************//**
*\n �������ƣ� usb_show_yuv422()
*\n ����������
*\n            usb���⴮��������ʾͼ��
*\n ���������
*\n            void *phandle  
*\n            uint8_t *buf   
*\n            int width      
*\n            int height     
*\n �������: 
*\n            
*\n �� �� ֵ:
*\n           0 �ɹ��� -1 ʧ��
*\n
*\n -------------------------------------------------------------------------
*\n  �汾:    �޸���:       �޸�����:         ����:
*\n   V0.1 	������ 	2018.10.17    	����
*******************************************************************************/
int usb_show_yuv422(void)
{
	static int index = 0;
	int ret;

#if  1
	yuv422_to_yuv420(yuv420, yuv422); // yuv422 ת yuv420��ʽ
	
	// USB����ͼ�����ָ�ʽ E_USB_FRAME_JPEG, E_USB_FRAME_YUV420P
	//ret = udp_send_data(yuv420, CAM_HSIZE * CAM_VSIZE, E_USB_FRAME_YUV420P);
	ret = udp_send_data(yuv420, CAM_HSIZE * CAM_VSIZE, E_USB_FRAME_JPEG);
	dbg_info("send %d frame, %d bytes\n", index++, ret);
	
	int size = udp_receive_data1(yuv420, CAM_HSIZE * CAM_VSIZE, NULL);
	if (size > 0)
	{
		yuv420[size] = '\0';
		dbg_debug("udp_receive[%d] = %s\n", size, yuv420);
	}
#endif

	return 0;
}

// ��image����copy��usbģ��
int memcpy2usb(/*void *dest,*/ const void *src, size_t n)
{
	memcpy(yuv422, src, n);
	return 0;

}


#endif // #if UDP_TEST_ENABLE



